package com.itheima.sfbx.insurance.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.itheima.sfbx.framework.commons.exception.ProjectException;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.framework.commons.utils.ExceptionsUtil;
import com.itheima.sfbx.insurance.dto.InsurancePlanVO;
import com.itheima.sfbx.insurance.dto.PlanEarningsVO;
import com.itheima.sfbx.insurance.dto.PlanSafeguardVO;
import com.itheima.sfbx.insurance.enums.InsurancePlanEnum;
import com.itheima.sfbx.insurance.mapper.InsurancePlanMapper;
import com.itheima.sfbx.insurance.pojo.InsurancePlan;
import com.itheima.sfbx.insurance.pojo.PlanEarnings;
import com.itheima.sfbx.insurance.pojo.PlanSafeguard;
import com.itheima.sfbx.insurance.service.IInsurancePlanService;
import com.itheima.sfbx.insurance.service.IPlanEarningsService;
import com.itheima.sfbx.insurance.service.IPlanSafeguardService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;
/**
 * @Description：保险方案服务实现类
 */
@Slf4j
@Service
public class InsurancePlanServiceImpl extends ServiceImpl<InsurancePlanMapper, InsurancePlan> implements IInsurancePlanService {

    @Autowired
    IPlanSafeguardService planSafeguardService;

    @Autowired
    IPlanEarningsService planEarningsService;

    @Autowired
    IdentifierGenerator identifierGenerator;


    /***
    * @description 保险方案多条件组合
    * @param insurancePlanVO 保险方案
    * @return QueryWrapper查询条件
    */
    private QueryWrapper<InsurancePlan> queryWrapper(InsurancePlanVO insurancePlanVO){
        QueryWrapper<InsurancePlan> queryWrapper = new QueryWrapper<>();
        //保险商品id查询
        if (!EmptyUtil.isNullOrEmpty(insurancePlanVO.getInsuranceId())) {
            queryWrapper.lambda().eq(InsurancePlan::getInsuranceId,insurancePlanVO.getInsuranceId());
        }
        //保险商品ids列表查询
        if (!EmptyUtil.isNullOrEmpty(insurancePlanVO.getInsuranceIds())) {
            queryWrapper.lambda().in(InsurancePlan::getInsuranceId,insurancePlanVO.getInsuranceIds());
        }
        //保险计划名称查询
        if (!EmptyUtil.isNullOrEmpty(insurancePlanVO.getPalnName())) {
            queryWrapper.lambda().eq(InsurancePlan::getPalnName,insurancePlanVO.getPalnName());
        }
        //默认定价查询
        if (!EmptyUtil.isNullOrEmpty(insurancePlanVO.getPrice())) {
            queryWrapper.lambda().eq(InsurancePlan::getPrice,insurancePlanVO.getPrice());
        }
        //默认定价单位：y/d,y/m,y/y查询
        if (!EmptyUtil.isNullOrEmpty(insurancePlanVO.getPriceUnit())) {
            queryWrapper.lambda().eq(InsurancePlan::getPriceUnit,insurancePlanVO.getPriceUnit());
        }
        //排序查询
        if (!EmptyUtil.isNullOrEmpty(insurancePlanVO.getSortNo())) {
            queryWrapper.lambda().eq(InsurancePlan::getSortNo,insurancePlanVO.getSortNo());
        }
        //状态查询
        if (!EmptyUtil.isNullOrEmpty(insurancePlanVO.getDataState())) {
            queryWrapper.lambda().eq(InsurancePlan::getDataState,insurancePlanVO.getDataState());
        }
        //按创建时间降序
        queryWrapper.lambda().orderByDesc(InsurancePlan::getCreateTime);
        return queryWrapper;
    }

    @Override
    public Page<InsurancePlanVO> findPage(InsurancePlanVO insurancePlanVO, int pageNum, int pageSize) {
        try {
            //构建分页对象
            Page<InsurancePlan> InsurancePlanPage = new Page<>(pageNum,pageSize);
            //构建查询条件
            QueryWrapper<InsurancePlan> queryWrapper = queryWrapper(insurancePlanVO);
            //执行分页查询
            Page<InsurancePlanVO> insurancePlanVOPage = BeanConv.toPage(page(InsurancePlanPage, queryWrapper), InsurancePlanVO.class);
            if (!EmptyUtil.isNullOrEmpty(insurancePlanVOPage.getRecords())){
                //补全方案保障项、给付计划
                Set<Long> planIds = insurancePlanVOPage.getRecords().stream().map(InsurancePlanVO::getId).collect(Collectors.toSet());
                //保障项
                List<PlanSafeguardVO> planSafeguardVOs = planSafeguardService.findInPlanId(planIds);
                List<PlanSafeguardVO> planSafeguardVOsHandler = Lists.newArrayList();
                //给付计划
                List<PlanEarningsVO> planEarningsVOs = planEarningsService.findInPlanId(planIds);
                insurancePlanVOPage.getRecords().forEach(n->{
                    planSafeguardVOs.forEach(i->{
                        if (n.getId().equals(i.getPlanId())) {
                            planSafeguardVOsHandler.add(i);
                        }
                    });
                    n.setPlanSafeguardVOs(planSafeguardVOsHandler);
                    planEarningsVOs.forEach(j->{
                        if (n.getId().equals(j.getPalnId())) {
                            n.setPlanEarningsVO(j);
                        }
                    });
                });
            }
            //返回结果
            return insurancePlanVOPage;
        }catch (Exception e){
            log.error("保险方案分页查询异常：{}", ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(InsurancePlanEnum.PAGE_FAIL);
        }
    }

    @Override
    public InsurancePlanVO findByIdAndInsuranceId(Long insurancePlanId,Long insuranceId){
        try {
            //执行查询
            QueryWrapper<InsurancePlan> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(InsurancePlan::getId,insurancePlanId).eq(InsurancePlan::getInsuranceId,insuranceId);
            InsurancePlanVO insurancePlanVO = BeanConv.toBean(getOne(queryWrapper), InsurancePlanVO.class);
            //方案保障项
            List<PlanSafeguardVO> planSafeguardVOs = planSafeguardService.findByPlanId(insurancePlanVO.getId());
            insurancePlanVO.setPlanSafeguardVOs(planSafeguardVOs);
            //方案给付计划
            PlanEarningsVO planEarningsVO =planEarningsService.findByPlanId(insurancePlanVO.getId());
            insurancePlanVO.setPlanEarningsVO(planEarningsVO);
            return insurancePlanVO;
        }catch (Exception e){
            log.error("保险方案单条查询异常：{}", ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(InsurancePlanEnum.FIND_ONE_FAIL);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean save(List<InsurancePlanVO> insurancePlanVOs) {
        // 先删除tab_insurance_plan数据、tab_plan_earnings、tab_plan_safeguard
        Long insuranceId = insurancePlanVOs.get(0).getInsuranceId();
        List<InsurancePlan> insurancePlanList = lambdaQuery()
                .eq(InsurancePlan::getInsuranceId, insuranceId)
                .list();

        // 不为空 删除
        if(CollUtil.isNotEmpty(insurancePlanList)){
            List<Long> ids = insurancePlanList.stream().map(InsurancePlan::getId).collect(Collectors.toList());
            // 删除tab_plan_earnings、tab_plan_safeguard
            planEarningsService.deleteInPlanId(ids);
            planSafeguardService.deleteInPlanId(ids);
            removeByIds(ids);
        }

        List<InsurancePlan> insurancePlans = new ArrayList<>();

        List<PlanSafeguard> planSafeguardVOList = new ArrayList<>();
        List<PlanEarnings> planEarningsVOList = new ArrayList<>();
        // 遍历insurancePlanVOs
        for (InsurancePlanVO insurancePlanVO : insurancePlanVOs) {
            InsurancePlan insurancePlan = BeanConv.toBean(insurancePlanVO, InsurancePlan.class);
            // 自己生成id
            Number id = identifierGenerator.nextId(insurancePlan);
            insurancePlan.setId(id.longValue());
            insurancePlan.setPlanNo(id.longValue());

            insurancePlans.add(insurancePlan);

            List<PlanSafeguardVO> planSafeguardVOs = insurancePlanVO.getPlanSafeguardVOs();
            if(CollUtil.isNotEmpty(planSafeguardVOs)){
                List<PlanSafeguard> planSafeguards = BeanConv.toBeanList(planSafeguardVOs, PlanSafeguard.class);
                for (PlanSafeguard planSafeguard : planSafeguards) {
                    planSafeguard.setPlanId(id.longValue());
                }
                planSafeguardVOList.addAll(planSafeguards);
            }

            PlanEarningsVO planEarningsVO = insurancePlanVO.getPlanEarningsVO();
            if(ObjectUtil.isNotNull(planEarningsVO)){
                PlanEarnings planEarnings = BeanConv.toBean(planEarningsVO, PlanEarnings.class);
                planEarnings.setPalnId(id.longValue());
                planEarningsVOList.add(planEarnings);
            }
        }

        saveBatch(insurancePlans);
        if (CollUtil.isNotEmpty(planEarningsVOList)) {
            planEarningsService.saveBatch(planEarningsVOList);
        }
        if (CollUtil.isNotEmpty(planSafeguardVOList)) {
            planSafeguardService.saveBatch(planSafeguardVOList);
        }

        return true;
    }

    @Override
    @Transactional
    public Boolean update(List<InsurancePlanVO> insurancePlanVOs) {

        //先删除，再新增
        Long insuranceId = insurancePlanVOs.get(0).getInsuranceId();
        //先把老的方案查出来
        List<InsurancePlan> list = lambdaQuery()
                .eq(InsurancePlan::getInsuranceId, insuranceId)
                .list();
        //找到方案id集合
        Set<Long> planIdSet = list.stream().map(InsurancePlan::getId).collect(Collectors.toSet());
        //删除对应的所有数据
        removeByIds(list.stream().map(InsurancePlan::getId).collect(Collectors.toSet()));
        planSafeguardService.remove(new LambdaQueryWrapper<PlanSafeguard>().in(PlanSafeguard::getPlanId,planIdSet));
        planEarningsService.remove(new LambdaQueryWrapper<PlanEarnings>().in(PlanEarnings::getPalnId,planIdSet));
        //从新保存
        return this.save(insurancePlanVOs);
    }

    @Override
    @Transactional
    public Boolean delete(String[] checkedIds) {
        try {
            List<Long> idsLong = Arrays.asList(checkedIds)
                .stream().map(Long::new).collect(Collectors.toList());
            boolean flag = removeByIds(idsLong);
            if (!flag){
                throw new RuntimeException("删除保险方案失败");
            }
            flag = planSafeguardService.deleteInPlanId(idsLong);
            if (!flag){
                throw new RuntimeException("删除保险方案保障项失败");
            }
            flag = planEarningsService.deleteInPlanId(idsLong);
            if (!flag){
                throw new RuntimeException("删除保险方案给付计划失败");
            }
            return flag;
        }catch (Exception e){
            log.error("删除保险方案异常：{}", ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(InsurancePlanEnum.DEL_FAIL);
        }
    }

    @Override
    public List<InsurancePlanVO> findList(InsurancePlanVO insurancePlanVO) {

        QueryWrapper<InsurancePlan> qw = queryWrapper(insurancePlanVO);
        // 一个保险有可能查出多个plan
        List<InsurancePlan> list = this.list(qw);

        List<Long> planIds = list.stream().map(InsurancePlan::getId).collect(Collectors.toList());

        // 一个plan有可能查出多个safeguard
        List<PlanSafeguard> safeguardList = planSafeguardService.lambdaQuery()
                .in(PlanSafeguard::getPlanId, planIds)
                .list();

        Map<Long, List<PlanSafeguard>> planSafeguardMap = safeguardList.stream().collect(Collectors.groupingBy(PlanSafeguard::getPlanId));

        // 几个plan对应几个earnings
        List<PlanEarnings> earningsList = planEarningsService.lambdaQuery()
                .in(PlanEarnings::getPalnId, planIds)
                .list();

        Map<Long, PlanEarnings> earningsMap = earningsList.stream().collect(Collectors.toMap(PlanEarnings::getPalnId, k -> k));

        List<InsurancePlanVO> insurancePlanVOS = BeanConv.toBeanList(list, InsurancePlanVO.class);
        for (InsurancePlanVO planVO : insurancePlanVOS) {
            List<PlanSafeguard> planSafeguards = planSafeguardMap.get(planVO.getId());
            List<PlanSafeguardVO> planSafeguardVOList = BeanConv.toBeanList(planSafeguards, PlanSafeguardVO.class);
            planVO.setPlanSafeguardVOs(planSafeguardVOList);

            PlanEarnings planEarnings = earningsMap.get(planVO.getId());
            PlanEarningsVO planEarningsVO = BeanConv.toBean(planEarnings, PlanEarningsVO.class);
            planVO.setPlanEarningsVO(planEarningsVO);
        }

        return insurancePlanVOS;
    }

}
